#ifndef AST_BLOCK
#define AST_BLOCK
#include <list>
#include <string>
#include "node.h"

namespace AST {

    /**
     * Bloco de Execução
     *
     * Durante as produções, um comando pode ser considerado como um bloco que
     * possui outros comandos definidos. Este bloco permite a declaração de
     * variáveis no início, caracterizando as variáveis de escopo.
     *
     * @category AST
     * @package  AST
     */
    class Block : public Node {

    private:

        /**
         * Conjunto de Declarações
         *
         * Variáveis declaradas no início do bloco, sendo definidas somente para
         * aquele escopo. Este conjunto trabalha com generalização de nós de
         * árvore abstrata de sintaxe, porém armazenam somente nós de
         * declarações de variáveis, conforme produção na gramática
         */
        std::list<AST::Node*>* _declarations;

        /**
         * Conjunto de Comandos
         *
         * Conjunto de instruções que manipulam informações de variáveis e
         * constantes descritas no código do programa. Armazena nós de árvore
         * abstrata de sintaxe, que pode armazenar, inclusive, outros blocos.
         */
        std::list<AST::Node*>* _commands;

        /**
         * Configuração de Declarações de Variáveis
         *
         * As declarações capturadas no início do bloco podem ser configuradas
         * neste nó de árvore abstrata de sintaxe, porém devem ser apresentados
         * em tempo de construção.
         *
         * @param  std::list<AST::Node*> Conjunto de Declarações
         * @return Block* Próprio Elemento para Encadeamento
         */
        Block* _setDeclarations(std::list<AST::Node*>*);

        /**
         * Configuração de Comandos e Instruções
         *
         * Conjunto que armazena os comandos ou instruções que são definidos
         * dentro do bloco de execução. Estes comandos podem possuir a mesma
         * definição de blocos, portanto podemos armazenar nós recursivos da
         * árvore.
         *
         * @param  std::list<AST::Node*>* Conjunto de Instruções
         * @return Block* Próprio Elemento para Encadeamento
         */
        Block* _setCommands(std::list<AST::Node*>*);

    public:

        /**
         * Construtor
         *
         * Execução responsável pela criação de novos blocos de execução. Estes
         * podem ser considerados como novos escopos de execução, onde recebem
         * declarações de variáveis no início do bloco definido.
         *
         * @param std::list<AST::Node*> Conjunto de Declarações de Variáveis
         * @param std::list<AST::Node*> Conjunto de Comandos Utilizados
         */
        Block(std::list<AST::Node*>*, std::list<AST::Node*>*);

        /**
         * Captura de Declarações de Variáveis
         *
         * Estrutura utilizada para apresentar o conjunto de declarações de
         * variáveis produzida no início do bloco de comandos.
         *
         * @return Conjunto de Declarações de Variáveis no Bloco
         */
        std::list<AST::Node*>* getDeclarations();

        /**
         * Captura de Instruções Utilizadas
         *
         * Apresenta a estrutura utilizada para armazenamento de comandos que
         * são utilizados dentro daquele escopo. São apresentados após a
         * definição de variáveis.
         *
         * @return Conjunto de Comandos no Bloco
         */
        std::list<AST::Node*>* getCommands();

        // Sobrescrita
        std::string toString(int);

    };

};

#endif

